#include "vector.h"
#include "rand.h"
#include <stdexcept>
#include <cmath>


Vector::Vector(unsigned int p_dimensions, unsigned int p_boundary)
    : m_dimensions(p_dimensions)
{
    double *components = new double[m_dimensions];

    // Obtain an uniform distribution of random cartesian components
    // ... inside a unit n-sphere.
    randy::random_sphere(m_dimensions, components);
    
    // Transform our unit components to the corresponding radius.
    for (unsigned int i = 0; i < m_dimensions; ++i) {
        m_components.push_back(components[i] * p_boundary);
    }

    delete components;
}

Vector::Vector(unsigned int p_dimensions, double p_value)
    : m_dimensions(p_dimensions)
{
    for (unsigned int i = 0; i < m_dimensions; ++i) {
        m_components.push_back(p_value);
    }
}

Vector::~Vector()
{

}

Vector::Vector(const Vector &p_vector)
{
    m_dimensions = p_vector.m_dimensions;
    m_components = p_vector.m_components;
}

double Vector::getComponent(unsigned int p_i) const
{
    if(p_i >= m_dimensions) {
        throw std::out_of_range("Vector:: Component index out of range.");
    }

    return m_components.at(p_i);
}

void Vector::setComponent(unsigned int p_i, double p_value)
{
    if(p_i >= m_dimensions) {
        throw std::out_of_range("Vector:: Component index out of range.");
    }

    m_components.at(p_i) = p_value;
}

int Vector::getComponentsSize() const
{
    return m_dimensions;
}

Vector &Vector::operator=(const Vector &p_vector)
{
    for(unsigned int i = 0; i < m_dimensions; ++i) {
        m_components.at(i) = p_vector.m_components.at(i);
    }

    return *this;
}

Vector &Vector::operator*=(double p_constant)
{
    for(unsigned int i = 0; i < m_dimensions; ++i) {
        m_components.at(i) *= p_constant;
    }

    return *this;
}
